﻿using ICSharpCode.AvalonEdit.Document;
using System;
using System.Collections;
using System.Collections.Generic;

namespace NFox.Pyeditor.Runtime
{
    public class AstTree2 : IEnumerable<AstTree2>
    {

        public TextLocation RealStart { get; private set; }

        public TextLocation Start { get; private set; }

        public TextLocation End { get; private set; }


        public string Name { get; private set; }

        List<AstTree2> _objs = new List<AstTree2>();
        List<AstTree2> _decs = new List<AstTree2>();
        dynamic _tree;
        TextDocument _doc;

        public IEnumerator<AstTree2> GetEnumerator()
        {
            foreach (var t in _decs)
                yield return t;
            foreach (var t in _objs)
                yield return t;
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        private AstTree2(string name, dynamic tree, TextDocument doc)
        {
            Name = name;
            _tree = tree;
            _doc = doc;
        }

        private void GetBody()
        {
            if (_tree.body is IEnumerable)
            {
                foreach (var t in _tree.body)
                {
                    Add(AstTree2.Parse(t, _doc));
                }
            }
            else
            {
                Add(AstTree2.Parse(_tree.body, _doc));
            }
        }

        private void GetDecorators()
        {
            foreach (var t in _tree.decorator_list)
            {
                AddDecorator(AstTree2.Parse(t, _doc));
            }
        }

        private void AddDecorator(AstTree2 tree)
        {
            if(tree.Start < RealStart)
            {
                RealStart = tree.Start;
            }
            int n = _decs.Count;
            if(n > 0)
            {
                var ftree = _tree[n - 1];
                int i = tree.Start.Line - 1;

            }
        }

        private void Add(AstTree2 tree)
        {
            int n = _objs.Count;
            _objs.Add(tree);

        }

        public static AstTree2 Parse(dynamic tree, TextDocument doc)
        {
            Type t = tree.GetType();
            string name = t.Name;
            var atree = new AstTree2(name, tree, doc);
            switch (name)
            {
                case "FunctionDef":
                case "ClassDef":
                    atree.RealStart = atree.Start = new TextLocation(tree.lineno, tree.col_offset);
                    atree.GetDecorators();
                    atree.GetBody();
                    break;
                case "Excepthandler":
                case "Interactive":
                case "Expression":
                case "Suite":
                case "For":
                case "While":
                case "If":
                case "Exec":
                case "Tryfinally":
                case "With":
                case "Tryexcept":
                case "Ifexp":
                case "Lambda":
                    atree.RealStart = atree.Start = new TextLocation(tree.lineno, tree.col_offset);
                    atree.GetBody();
                    break;
                case "Module":
                    atree.RealStart = atree.Start = new TextLocation(1, 0);
                    atree.End = doc.GetLocation(doc.TextLength);
                    atree.GetBody();
                    break;
            }
            return atree;
        }

    }
}
